/*
 * Copyright (C) 2008 Peter Kling
 *
 * This file is part of 'A Kind of Billiard', a graphical billiard simulation.
 *
 * 'A Kind of Billiard' is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * 'A Kind of Billiard' is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * 'A Kind of Billiard'. If not, see <http://www.gnu.org/licenses/>.
 */

package cg2.mathematics;

/**
 * @brief Simple matrix implementation.
 */
public class MathMatrix implements Cloneable {
	// storage for matrix data (column-major order)
	private double[] data;

	// number of rows/columns
	public final int n, m;
	
	/**
	 * @brief Constructs an (n x m)-unit-matrix.
	 */
	public MathMatrix(int n, int m) {
		data = new double[n*m];
		this.n = n;
		this.m = m;
	}
	
	/**
	 * @brief Adds the given (n x m)-matrix to this one.
	 * @throws IllegalArgumentException if matrix dimensions do not match.
	 */
	public void add(MathMatrix matrix) {
		if (matrix.n != n || matrix.m != m)
			throw new IllegalArgumentException("Matrix dimensions do not match.");
		for (int i=0; i<n; i++)
			for (int j=0; j<m; j++)
				data[j*n+i] += matrix.get(i,j);
	}
	
	/**
	 * @brief Returns a copy of this matrix.
	 */
	@Override
	public MathMatrix clone() {
		MathMatrix matrix = new MathMatrix(n, m);
		matrix.add(this);
		return matrix;
	}
	
	/**
	 * @brief Returns the matrix element in row i and column j (numbering starts with zero).
	 */
	public double get(int i, int j) {
		return data[j*n+i];
	}
	
	/**
	 * @brief Returns the array reference to the internal data in column major order.
	 */
	public double[] getData() {
		return data;
	}
	
	/**
	 * @brief Sets the matrix element in row i and column j (numbering starts with zero).
	 */
	public void set(int i, int j, double value) {
		data[j*n+i] = value;
	}
	
	/**
	 * @brief Returns a readable representation of this matrix.
	 */
	public String toString() {
		String str = "";
		for (int i=0; i<n; i++) {
			for (int j=0; j<m-1; j++)
				str += get(i,j) + "\t";
			str += get(i,m-1) + "\n";
		}
		return str;
	}
}
